#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#define SIZE 5
using namespace std;
template <class T>
class RingQueue
{
public:
    RingQueue()
        : _capacity(SIZE),
          _ring(SIZE)
    {
        sem_init(&_customer, 0, 0);
        sem_init(&_productor, 0, _capacity);
        pthread_mutex_init(&_mutex_productor,nullptr);
        pthread_mutex_init(&_mutex_customer,nullptr);
    }

    ~RingQueue()
    {
        sem_destroy(&_customer);
        sem_destroy(&_productor);

        pthread_mutex_destroy(&_mutex_customer);
        pthread_mutex_destroy(&_mutex_productor);
    }

    void push(const T &data)
    {
        sem_wait(&_productor);
        pthread_mutex_lock(&_mutex_productor);
        _ring[_pos_productor++] = data;
        _pos_productor %= _capacity;
        pthread_mutex_unlock(&_mutex_productor);
        sem_post(&_customer);
    }

    void pop(T *data)
    {
        sem_wait(&_customer);
        pthread_mutex_lock(&_mutex_customer);
        *data = _ring[_pos_customer++];
        _pos_customer %= _capacity;
        pthread_mutex_unlock(&_mutex_customer);
        sem_post(&_productor);
    }

private:
    vector<T> _ring;
    int _capacity;//环形队列容器大小
    sem_t _customer;//只有消费者关心的数据
    sem_t _productor;//只有生产者关心的空间
    int _pos_customer = 0;//消费位置
    int _pos_productor = 0;//生产位置
    pthread_mutex_t _mutex_customer;
    pthread_mutex_t _mutex_productor;
};
